<!DOCTYPE html>
<html>
  <head>
    <title>视频人脸检测</title>
    <style>
      #videoContainer {
        position: relative;
        /* max-width: 800px; */
      }
      #video,
      #canvas {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: auto;
      }
      #canvas {
        pointer-events: none;
      }
      /* 添加播放按钮样式 */
      #playBtn {
        padding: 12px 24px;
        background: #4caf50;
        color: white;
        border: none;
        cursor: pointer;
        margin: 10px;
      }
      #showPeople img {
        display: inline-block;
      }
    </style>
  </head>
  <body>
    <button id="playBtn">点击播放并开始检测</button>
    <div id="videoContainer">
      <video id="video" controls muted>
        <source src="./2025419-450082.mp4" type="video/mp4" />
        您的浏览器不支持视频标签
      </video>
      <canvas id="canvas"></canvas>
      <hr />
      <div id="showPeople"></div>
    </div>

    <!-- 引入face-api.js -->
    <script src="./js/face-api.min.js"></script>

    <script>
      const video = document.getElementById("video");
      const canvas = document.getElementById("canvas");
      const playBtn = document.getElementById("playBtn");
      const showPeople = document.getElementById("showPeople");

      function getImage(box) {
        // 创建新的画布
        const newCanvas = document.createElement("canvas");
        const newCtx = newCanvas.getContext("2d");

        // 设置新画布的尺寸为截取区域的大小
        newCanvas.width = box.width;
        newCanvas.height = box.height;
        
        // 从原始画布上绘制截取区域到新画布
        newCtx.drawImage(
          video,
          box.x,
          box.y,
          box.width,
          box.height,
          0,
          0,
          box.width,
          box.height
        );

        // 导出为 Base64 编码的图像数据
        const base64Data = newCanvas.toDataURL("image/png");

        // 在图像元素中显示截取的图像
        // outputImage.src = base64Data;
        let showPeople = document.getElementById("showPeople");
        let img = document.createElement("img");
        img.src = base64Data;
        showPeople.append(img);
        // console.log("Base64 数据:", base64Data);
      }

      // 初始化函数
      async function init() {
        // 加载人脸检测模型
        await faceapi.nets.tinyFaceDetector.loadFromUri(
          "./face-api.js-master/weights"
        );

        // 设置视频尺寸同步到canvas
        canvas.height = video.videoHeight;
        canvas.width = video.videoWidth;
        showPeople.style.marginTop = `${10 + video.clientHeight}px`
      }

      // 开始检测
      async function startDetection() {
        const ctx = canvas.getContext("2d");

        // 使用requestAnimationFrame实现流畅检测
        const detectFrame = async () => {
          if (!video.paused && !video.ended) {
            // 检测人脸
            const detections = await faceapi.detectAllFaces(
              video,
              new faceapi.TinyFaceDetectorOptions()
            );

            // 清空画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            // console.log(detections)
            // 绘制检测框

            detections.forEach((detection) => {
              const box = detection.box;
              // console.log(box);

              ctx.save(); // 保存当前上下文状态
              ctx.beginPath();
              ctx.rect(box.x, box.y, box.width, box.height);
              ctx.strokeStyle = "#ff0000";
              ctx.lineWidth = 1;
              ctx.stroke();
              ctx.restore(); // 恢复之前保存的上下文状态

              getImage(box);
            });
          }
          requestAnimationFrame(detectFrame);
        };
        detectFrame();
      }

      // 播放按钮点击事件
      playBtn.addEventListener("click", async () => {
        try {
          await video.play();
          startDetection();
          playBtn.style.display = "none"; // 隐藏按钮
        } catch (err) {
          alert("视频播放失败: " + err.message);
        }
      });

      // 初始化
      window.onload = init;
    </script>
  </body>
</html>
